require 'digest/sha1'
class User < ActiveRecord::Base
  # Virtual attribute for the unencrypted password
  attr_accessor :password

  validates_presence_of     :password,                   :if => :password_required?
  validates_presence_of     :password_confirmation,      :if => :password_required?
  validates_length_of       :password, :within => 4..40, :if => :password_required?
  validates_confirmation_of :password,                   :if => :password_required?
  validates_presence_of     :login
  validates_length_of       :login,    :within => 3..40
  validates_presence_of     :email
  validates_length_of       :email,    :within => 3..100
  validates_format_of       :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/
  validates_uniqueness_of   :login, :email, :case_sensitive => false
  validates_presence_of     :mobile
  validates_presence_of     :postal_code
  
  before_save :encrypt_password
  before_create :make_activation_code 
  
  has_one  :avatar, :dependent => :destroy
  has_many :places, :dependent => :destroy
  has_many :events, :order => "starts_at", :dependent => :destroy
  has_many :contacts, :dependent => :destroy
  has_many :confirmed_events, :through => :contacts, :source => :event, :order => "starts_at", :conditions => ["contacts.confirm = ?", true]
  has_many :denied_events, :through => :contacts, :source => :event, :order => "starts_at", :conditions => ["contacts.confirm = ?", false]
  has_many :contacts, :dependent => :destroy
  has_many :friendings, :dependent => :destroy
  has_many :friends, :through => :friendings, :class_name => 'User', :foreign_key => 'friend_id'
  has_many :passive_friendings, :class_name => 'Friending', :foreign_key => 'friend_id', :dependent => :destroy
  has_many :passive_friends, :through => :passive_friendings, 
           :class_name => 'User', :foreign_key => 'user_id', :source => :user
  
  # prevents a user from submitting a crafted form that bypasses activation
  # anything else you want your user to change should be added here.
  attr_accessible :login, :name, :surname, :email, :password, :password_confirmation, :postal_code, :mobile, :address, :birthdate, :city
  
  def validate
    if RESERVED_WORDS and RESERVED_WORDS.include?(login) and new_record?
      errors.add(:login, "El nombre de usuario que has elegido ya existe. Por favor elige otro")
    end
  end
  
  # Activates the user in the database.
  def activate
    @activated = true
    self.activated_at = Time.now.utc
    self.activation_code = nil
    save(false)
  end

  def activated?
    # the existence of an activation code means they have not activated yet
    activation_code.nil?
  end

  # Returns true if the user has just been activated.
  def recently_activated?
    @activated
  end

  # Authenticates a user by their login name and unencrypted password.  Returns the user or nil.
  def self.authenticate(login, password)
    u = find :first, :conditions => ['login = ? and activated_at IS NOT NULL', login] # need to get the salt
    u ||= find :first, :conditions => ['email = ? and activated_at IS NOT NULL', login] # need to get the salt
    u && u.authenticated?(password) ? u : nil
  end

  # Encrypts some data with the salt.
  def self.encrypt(password, salt)
    Digest::SHA1.hexdigest("--#{salt}--#{password}--") 
  end

  # Encrypts the password with the user salt
  def encrypt(password)
    self.class.encrypt(password, salt)
  end

  def authenticated?(password)
    crypted_password == encrypt(password)
  end

  def remember_token?
    remember_token_expires_at && Time.now.utc < remember_token_expires_at 
  end

  # These create and unset the fields required for remembering users between browser closes
  def remember_me
    remember_me_for 2.weeks
  end

  def remember_me_for(time)
    remember_me_until time.from_now.utc
  end

  def remember_me_until(time)
    self.remember_token_expires_at = time
    self.remember_token            = encrypt("#{email}--#{remember_token_expires_at}")
    save(false)
  end

  def forget_me
    self.remember_token_expires_at = nil
    self.remember_token            = nil
    save(false)
  end

  # Metodos que nosotros añadimos al usuario
  def public_name
    if self.name.blank?
      self.login
    else
      self.name
    end
  end
  
  def get_avatar(size=nil)
    size = size.to_sym unless size.nil?
    if self.avatar.nil?
      case size
        when :thumb
          '/images/default_avatar_thumb.gif'
        when :mini
          '/images/default_avatar_mini.gif'
        else
          '/images/default_avatar.gif'
      end
    else
      self.avatar.public_filename(size)
    end
  end
  
  def update_avatar(uploaded_data)
    self.avatar.destroy unless self.avatar.nil?
    self.avatar = Avatar.create(:uploaded_data => uploaded_data)
    save
  end
  
  def has_event?(event)
    return true if event.user == self
    return true unless self.contacts.find_by_event_id(event.id).blank?
    return false
  end
  
  def has_friend?(user)
    return true unless self.friendings.find_by_friend_id(user.id).blank?
    return false
  end
  
  def is_admin?
    return true if self.admin?
    return false
  end
    
  protected
    # before filter 
    def encrypt_password
      return if password.blank?
      self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
      self.crypted_password = encrypt(password)
    end
    
    def password_required?
      crypted_password.blank? || !password.blank?
    end
    
    def make_activation_code
      self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
    end 
end
